#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>
#include <readline/history.h>

#include "cli.h"

extern T_Command CmdSet_Def[];  //指令集

static int g_start = 0;  //补全起始位置

/**
 * @brief 自动补全回调函数
 * 
 * @param text 用户当前输入的部分文本()，用于匹配命令列表中的命令
 * @param state 一个整数，表示当前匹配的状态。补全函数被反复调用时，state 的值会变化
 * @return char* 匹配的命令
*/
static char *command_generator(const char *text, int state)
{
    static int list_index, len;
    static char *sub_cmd;
    const char delim[] = " ";
    char *temp;
    char cmd[64];

    if (!state)
    {
        free(sub_cmd);
        list_index = 0;
        sub_cmd = strdup(rl_line_buffer);  //当前命令行的输入内容(不能直接访问rl_line_buffer)
        len = rl_point;            //输入内容长度
    }
    
    while (temp = CmdSet_Def[list_index++].command)
    {
        if (strncmp(temp, sub_cmd, len) == 0)
        {
            strncpy(cmd, temp, strlen(temp));
            cmd[strlen(temp)] = '\0';

            /*获取子命令*/
            char *token = strtok(cmd+g_start, delim); 
            if (token != NULL){
                return strdup(token);
            }   
        }
        /*打印提示信息*/
        else if(!strncmp(temp,sub_cmd,strlen(temp)))
        {
            printf("\r\n");
            printf("\r\n%s\r\n",CmdSet_Def[list_index-1].help);
            printf("\r\n");
            rl_forced_update_display();
            return NULL;
        }
        //list_index++;
    }
    return NULL;
}

/**rl_completion_matches 会调用 command_generator 函数，
 * 生成所有匹配 text 的命令，并返回一个以 NULL 结尾的字符串数组。
 * rl_attempted_completion_over 设为 1，表示不使用默认的文件名补全，而是使用自定义的补全逻辑。
 */
/**
 * @brief 字符串自动补全函数
 * 
 * @param text 用户当前输入的部分文本，用于匹配命令列表中的命令
 * @param start text在输入行中的位置。
 * @param end 输入行中补全结束的位置。
 * @return char** 匹配的命令
*/
static char **command_completion(const char *text, int start, int end) {
    rl_attempted_completion_over = 1;
    g_start = start;
    return rl_completion_matches(text, command_generator);
}

/**
 * @brief 命令回调函数
 * 
 * @param input 命令
*/
static void execute_command(const char *input) {
    PT_Command ptTemp;
    char *temp = strdup(input);
    int iLen = 0;
    int i = 0;
    char *cmd_seg[COMMAND_MAX_LEN];

    /*分段获取输入内容(参数部分)*/
    cmd_seg[iLen] = strtok(temp, " ");
    while (cmd_seg[iLen] != NULL && iLen < COMMAND_MAX_LEN - 1) {
        cmd_seg[++iLen] = strtok(NULL, " ");  
    }

    ptTemp = CmdSet_Def;
    while(ptTemp->command) {
        if (strncmp(input, ptTemp->command, strlen(ptTemp->command)) == 0) {

            char **parms = malloc(ptTemp->iParmsNum * sizeof(char *));
            for (i = 0; i < ptTemp->iParmsNum; i++)
            {
                parms[i] = cmd_seg[iLen - ptTemp->iParmsNum + i];
                //printf("parms[%d] = %s\n", i, parms[i]);
            }

            ptTemp->command_fuc(ptTemp->iParmsNum,parms,ptTemp);
            goto finish;
        }
        ptTemp++;
    }
    printf("command not found\r\n");
finish:
    free(temp);
}

/**
 * @brief cli模块逻辑
 */
int main() {
    char *input;

    // 设置自动补全函数
    rl_attempted_completion_function = command_completion;

    while ((input = readline(">>> ")) != NULL) {
        // 如果输入不为空，将输入添加到历史记录中
        if (*input) {
            add_history(input);
            execute_command(input);
        }
        free(input);
    }
    return 0;
}
